#-*- coding: utf8 -*-
import nose
from pyson.schema import *

def assert_f(rel, msg=''):
        assert rel, msg

class examples(object):
    class __metaclass__(type):
        '''Factory function that define tests from examples for the type sch.'''

        def __new__(cls, name, bases, names):
            if name == 'examples':
                return type.__new__(cls, name, bases, names)
            else:
                schema = names['schema']
                examples = names['examples']

                def retfunc():
                    for value in examples:
                        try:
                            obj, value = value
                            msg = '%s(%s) ==> %s' % (schema.label, obj, value)
                        except:
                            obj, value, msg = value
                        yield assert_f, schema.isvalid(obj) == value, msg

                retfunc.__name__ = name
                return retfunc

def multiexamples(*args):
    '''Factory function that define tests from examples for multiple types'''

    def func():
        for (sch, obj, value) in args:
            yield lambda x: sch.isvalid(obj) == x, value
    return func

#===============================================================================
# Numeric testers
#===============================================================================
class testNumeric(examples):
    schema = Numeric()
    examples = [
        ('1', False),
        (1, True),
        (2.0, True),
        (2.0 + 1j, True), ]

class testNumericRange(examples):
    schema = Numeric(min=0, max=10)
    examples = [
        (1, True),
        (20, False),
        (2.0 + 1j, False), ]

class testNumber(examples):
    schema = Number()
    examples = [
        ('1', False),
        (1, True),
        (2.0, True),
        (2.0 + 1j, False), ]

class testFloat(examples):
    schema = Float()
    examples = [(1, False), (2.0, True)]

class testInt(examples):
    schema = Integer()
    examples = [(1, True), (2.0, False)]

class testBool(examples):
    schema = Bool()
    examples = [(2.0, False), (True, True), (False, True), (0, False)]

#===============================================================================
# String tests
#===============================================================================
class testStr(examples):
    schema = Str()
    examples = [('foo', True), (u'foo', True), (None, False)]

class testStrLen(examples):
    schema = Str(maxlength=5)
    examples = [('foo', True), (u'foo-bar', False)]

class testStrEncoding(examples):
    schema = Str(encoding='ascii')
    examples = [('fôo', False), (u'foo-bar', True), (u'fôo', False)]

class testEmail(examples):
    schema = Email()
    examples = [('foobar', False), ('foo@bar.com.br', True), (u'foo@bar.com', True)]


if __name__ == '__main__':
    nose.main()
